/**
 * 
 */
package cn.jhz.filesharingsystem.service;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;

import cn.jhz.filesharingsystem.dao.IndexDao;
import cn.jhz.filesharingsystem.dao.SharedFileDao;
import cn.jhz.filesharingsystem.dao.UserDao;
import cn.jhz.filesharingsystem.model.Pager;
import cn.jhz.filesharingsystem.model.SharedFile;
import cn.jhz.filesharingsystem.model.User;
import cn.jhz.filesharingsystem.util.UploadPropertiesUtil;

/**
 * @author asus
 *
 */
@Service("sharedFileService")
public class SharedFileServiceImpl extends BaseServiceImpl<SharedFile> implements SharedFileService {
	
	static private String separator = System.getProperty("file.separator");
	
	@Autowired
	private IndexDao indexDao;
	
	@Autowired
	private UserDao userDao;
	@Override
	public List<SharedFile> getAllFile() {
		return ((SharedFileDao)baseDao).getAllFile();
	}

	@Override
	public Pager<SharedFile> getAllPagerFile(String filename, int provider, boolean state) {
		return ((SharedFileDao)baseDao).getAllPagerFile(filename, provider, state);
	}

	@Override
	public void saveFile(
			User provider, Integer state,String notes, MultipartFile uploadfile) 
					throws IOException {

		String fileName = "";
		//文件原名
		String saveFileName = "";
		//保存文件的服务器上的名字
		String savePath = UploadPropertiesUtil.getInstance().getProperty("savePath");
		//生成保存文件的服务器上的绝对路径
		Path path;
	
		/* 创建文件名 */
		fileName = uploadfile.getOriginalFilename();
		fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);				

		/* 7.获取普通表单域将上传的文件信息,写入数据库                                       
		   	  获取上传的文件信息和各种文本                                                            
		         文件类型   文件名   文件大小                                                                
		(注意事项:IE的时带有绝对路径;火狐只有文件名)windows使用\需要转义 */
		/* 8.验证后缀的合法性*/
		/* 9.将文件流写入保存的目录中
		(生成新的文件名,避免一个目录中文件太多而生成新的存储目录)*/
				saveFileName = makeFileName(fileName);
				path = Paths.get(makePath(saveFileName, savePath), saveFileName);
				if (fileName == null || fileName.trim().equals("")
						||saveFileName.trim().equals("")||saveFileName == null
						||path.toString().trim().equals("")||path == null) {
					throw new MultipartException("文件名或路径为null");
				}

				try(BufferedInputStream input = new BufferedInputStream(uploadfile.getInputStream());
					BufferedOutputStream output	= new BufferedOutputStream(Files.newOutputStream(path))){

					int len = 0;
					byte[]buf = new byte[8192];
					while((len = input.read(buf))!=-1) {
						output.write(buf,0,len);
					}
					submitInfo(provider, state,fileName,String.valueOf(uploadfile.getSize())
							,saveFileName,path.toString(),uploadfile.getContentType(),notes);

				} catch (IOException e) {
					// TODO Auto-generated catch block
					throw e;
				}

				User user = userDao.loadUserByEmail(provider.getEmail());
				provider.setFiles(user.getFiles());
	}
	
	@Override
	public void updateState(Integer fileId) throws IOException {

		SharedFile fileDB = baseDao.load(fileId);
		if(fileDB.getState()>0) {
			indexDao.deleteIndex(fileDB.getIndex());
		}else {
			indexDao.addIndex(fileDB);
		}
		//load从数据库拿到预修改的用户记录对应的file对象，这个file对象就会直接进入到hibernate的一个缓存里	
		fileDB.setState(fileDB.getState()>0?0:1);
		baseDao.update(fileDB);
	}
	
	public void deleteRecord(SharedFile deletefile) throws IOException {
		//解除主从关系
	//	SharedFile file = load(id);
		User tempUser = deletefile.getProvider();
		
		
		deletefile.setProvider(null);
		tempUser.getFiles().remove(deletefile);
		userDao.update(tempUser);
		update(deletefile);
		
		indexDao.deleteIndex(deletefile.getIndex());
		baseDao.delete(deletefile.getId());
		//先清除数据库记录,在删除文件
		deleteFile(deletefile.getSavePath());
		
	}
	
	private void deleteFile(String savePath) throws IOException {
		Path path =Paths.get(savePath);
		Files.deleteIfExists(path);
	}
	
	@Override
	public byte[] download(int id, HttpHeaders headers) throws IOException {
		/* 1.获取要下载的文件的绝对路径 */
		SharedFile downloadFile = baseDao.load(id);
		/* 2.获取文件名(针对IE或者以IE为内核的浏览器：解决下载的时候文件名是中文乱码) */
		headers.setContentDispositionFormData("attachment"
				, new String(downloadFile.getFileName().getBytes("UTF-8"),"ISO-8859-1"));
		return FileUtils.readFileToByteArray(new File(downloadFile.getSavePath()));	
	}
	
	@Override
	public void download(SharedFile file, HttpServletRequest req, HttpServletResponse resp) throws IOException {
		String filePath = file.getSavePath();
		// 1.获取要下载的文件的绝对路径
		String fileName = file.getFileName();
		// 2.获取文件名
		String userAgent = req.getHeader("User-Agent");
		// 3.设置header
		/* 针对IE或者以IE为内核的浏览器：解决下载的时候文件名是中文乱码 */
		if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
			/* IE浏览器的处理 */
			fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
		} else {
			/* 非IE浏览器的处理 */
			fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
		}
		/* 3.设置content-disposition响应头控制浏览器以下载的方式打开文件 */
		resp.setHeader("content-disposition", "attachment;filename=" + fileName);
		resp.setCharacterEncoding("utf-8");
		resp.setContentType("multipart/form-data");

		/* 4.获取要下载文件输入流 */
		try (InputStream in = new FileInputStream(filePath); OutputStream out = resp.getOutputStream()) {
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = in.read(buffer)) > 0) {
				out.write(buffer, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private String makeFileName(String fileName) {
		return UUID.randomUUID().toString()+""+fileName;
	}
	
	private String makePath(String saveFileName, String savePath) throws IOException {
		//获取文件名字,在内存中的地址,hashcode值
		int hashCode = saveFileName.hashCode();
		int dir1 = hashCode&0xf;  //dir1的值,与运算的结果范围0-15
		int dir2 = ( hashCode>> 4)&0xf ; //结果还是0-15
		//用dir1,dir2构造新的存储文件的目录
		Path path = Paths.get(savePath + separator + dir1 + separator + dir2);
		//windows使用\ Linux使用/
        if(!Files.isDirectory(path)) {
        	Files.createDirectories(path);
        }	
		return path.toString();
	}
	
	private void submitInfo(User provider, Integer state, String...info) throws IOException {

		SharedFile fileInfo = new SharedFile();
		fileInfo.setFileName(info[0]);
		fileInfo.setFileSize(Long.parseLong(info[1]));
		fileInfo.setSaveName(info[2]);
		fileInfo.setSavePath(info[3]);
		fileInfo.setFileType(info[4]);
		fileInfo.setNotes(info[5]);
		fileInfo.setProvider(provider);
		fileInfo.setState(state);
		

		//通过UUID生成一个唯一的随机数
		String articleId = UUID.randomUUID().toString();
		
		fileInfo.setIndex(articleId); 
		baseDao.add(fileInfo);
		if(fileInfo.getState()>0)
			indexDao.addIndex(fileInfo);
	}

//	
//
//
//	@Override
//	public void addIndex(SharedFile index) throws IOException {
//		 ((SharedFileDao)baseDao).addIndex(index);
//	}
//
//	@Override
//	public void deleteIndex(String id) throws IOException {
//		((SharedFileDao)baseDao).deleteIndex(id);
//	}
//
//	@Override
//	public void updateIndex(SharedFile index) throws IOException {
//		((SharedFileDao)baseDao).updateIndex(index);
//	}	
	
}
